<?php

namespace App\System\Base\Services;

use App\Exceptions\Customize\ParamsException;
use App\Exceptions\Customize\TokenException;
use App\Exceptions\Customize\WeChatException;
use App\System\Cis\Model\CisUser;
use App\System\Cis\Model\CisUserAuth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Request;

class UserTokenService extends TokenService
{
    private $js_code;   //微信小程序code
    private $appid;     //微信小程序appid
    private $app_secret; //微信小程序密钥
    private $openid_url; //获取openid地址

    /**
     * 初始化成员变量
     * UserTokenService constructor.
     * @param $js_code
     */
    public function __construct($js_code)
    {
        $this->js_code = $js_code;
        $this->appid = config('global.s_appid');
        $this->app_secret = config('global.s_app_secret');
        //使用sprintf函数拼接url地址
        $this->openid_url = sprintf(config('global.s_openid_url'), $this->appid, $this->app_secret, $this->js_code);
    }

    /**
     * 入口，获取Token
     * @return string
     * @throws \Exception
     */
    public function get()
    {
        if (config("app.env") == 'production') {//生产环境才使用授权
            $result = curl_get($this->openid_url);
            $wx_result = json_decode($result, true);
            //检查微信返回结果
            if (empty($wx_result)) {
                throw new \Exception('请求openid和session_key时发生空异常，微信内部错误');
            } else if (array_key_exists('errmsg', $wx_result)) {
                $this->requestOpenidError($wx_result);
            }
        } else {
            $wx_result['openid'] = 111122111;
        }
        //颁发令牌
        $token = $this->saveToCache($wx_result);
        //返回Token到客户端
        return $token;
    }

    /**
     * 返回微信错误
     * @param $wx_result
     * @throws WeChatException
     */
    private function requestOpenidError($wx_result)
    {
        throw new WeChatException([
            'message'    => $wx_result['errmsg'],
            'error_code' => $wx_result['errcode']
        ]);
    }

    /**
     * 保存到缓存
     * @param $wx_result
     * @return string
     * @throws TokenException
     */
    private function saveToCache($wx_result)
    {
        //获得Token作为缓存的key
        $key = self::generateToken();
        //保存时间
        $token_expire = config('global.token_expire');

        $user_Auth = CisUserAuth::where('open_id', $wx_result['openid'])->first();
        if (!$user_Auth) {
            $request = Request::instance();
            $image_url = isset($request->q['imagePath']) ? $request->q['imagePath'] : '';
            $set = array('nickname' => $request->q['nickName'], 'image_path' => $image_url);
            $refereeId = isset($request->q['refereeId']) ? $request->q['refereeId'] : 0;
            if ((int)$refereeId) {//有推荐人
                $referee_user = CisUser::where('id', $refereeId)->first();
                if ($referee_user) {
                    $set['referee_id'] = $referee_user->id;
                    $referee_user->referee_number = $referee_user->referee_number + 1;
                    $referee_user->save();
                }
            }
            $user = CisUser::create($set);
            if (!$user) {
                throw new TokenException([
                    'message' => '用户生成失败'
                ]);
            }
            $uid = $user->id;
            $unionid = isset($wx_result['unionid']) ? $wx_result['unionid'] : '';
            if (isset($set['referee_id'])) {
                unset($set['referee_id']);
            }
            $set = array_merge($set, array('partner' => 13, 'unionid' => $unionid, 'user_id' => $user->id, 'open_id' => $wx_result['openid']));
            $auth_id = CisUserAuth::create($set);
            if (!$auth_id) {
                throw new TokenException([
                    'message' => '用户生成失败'
                ]);
            }
        } else {
            $uid = $user_Auth->user_id;
            $user = CisUser::where('id', $user_Auth->user_id)->where("status", 1)->first();
            if (!$user) {
                throw new ParamsException(['error_code' => '1106', 'message' => '账号不存在或已停用！']);
            }
        }
        $wx_result['uid'] = $uid;
        $value = json_encode($wx_result);
        //文件缓存
        Cache::put($key, $value, $token_expire);
        if (!Cache::has($key)) {
            throw new TokenException([
                'message' => '服务器缓存SessionId失败'
            ]);
        }
        return $key;
    }
}